#ifndef Filter_HOUGH_CIRCLE_H
#define Filter_HOUGH_CIRCLE_H

#include <iostream>
#include <QObject>
#include <QtGui>
#include <common/interfaces.h>
#include <vector>
#include <limits>
#include "Circle.h"
#include "HoughSpace.h"

class QScriptEngine;

class Filter_Hough_Circle : public QObject, public MeshFilterInterface
{
	/* Pour pouvoir afficher le plugin dans le menu meshlab */
    Q_OBJECT
    Q_INTERFACES(MeshFilterInterface)

public:
	
    enum { FP_HOUGH_CIRCLE } ;
	
	/* Constructeur */
	Filter_Hough_Circle();
	
	virtual QString pluginName(void) const { return "HoughCirclePlugin"; }
	
	QString filterName(FilterIDType filter) const;
	QString filterInfo(FilterIDType filter) const;
	FilterClass getClass(QAction *a);
	void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
	QString filterScriptFunctionName(FilterIDType filterID);
	
	/* Appelle le filtre */
	bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
	
	/* *********************************************************************************************************** */
	/* ***************************************** METHODES SUPPLEMENTAIRES **************************************** */
	/* *********************************************************************************************************** */
	/* ***
	   *** Les méthodes init_meshModel, init_grid et init_filter peuvent se réécrire sans arguments, en s'appuyant sur les attributs de la classe directement
	   ***
	*/
	
	/* Initialise la référence du meshmodel de la classe avec le MeshDocument passé en parametre du pligin */
	void init_meshModel ( MeshDocument &md );
	
	/* Plonge le maillage dans une grille carrée de résolution en X et en Y données */
	void init_grid ( MeshModel* _mesh, RichParameterSet &par, int _resZ = 1 );
	
	/* Plonge le maillage dans une grille carrée qui recoupe la première grille */
	void init_grid2 ( MeshModel* _mesh, RichParameterSet &par, int _resZ = 1 );
	
	/* Rempli le tableau ptsMin de la classe avec les points d'altitudes minimum de chaque case de la grille passée en paramètre */
	void init_ptsMin ( const vcg::GridStaticPtr<CVertexO,float>& _grid );
	
	/* Initialise tous les attributs de la classe du filtre */
	void init_filter ( MeshDocument &md, RichParameterSet &par );
	
	/* Coupe le nuage de points entre deux seuils de hauteurs, renoie false si un problème est survenu (dans lesa rguments) */
	bool sliceMesh ( float _lowThresh, float _highTresh, vcg::CallBackPos *cb, int _nbPtsInSlice );
	
	/* Prends une cellule de la grille, crée un espace de Hough y correspondant et le rempli avec les cercles trouvés dans la cellule. Renvoie ensuite un tableau de cercles pertinents */
	vector<Circle> hsCell ( vcg::GridStaticPtr<CVertexO,float> _grid, vcg::GridStaticPtr<CVertexO,float>::Cell* _cell, RichParameterSet &par );
	
	/* Fait hough sur une grille et renvoie les cercles pertinents */
	vector<Circle> hsGrid ( vcg::GridStaticPtr<CVertexO,float> _grid, RichParameterSet &par, vcg::CallBackPos *cb );
	
	/* Fait hough sur les deux grilles du filtre et renvoie le tableau de cercles associés */
	vector<Circle> hsCloud ( RichParameterSet &par, vcg::CallBackPos *cb );
	
	static void addCircleToMesh ( CMeshO& _mesh, Circle _c, float _height );
	
private :
		/* On y met un MeshModel qui contiendra une copie du modele passé en parametre du plugin et sur lequel on va faire tourner le filtre */
		MeshModel* mesh;
		
		/* Ce filtre a une grille pour y plonger les vertex dedans */
		vcg::GridStaticPtr<CVertexO,float> grid;
		
		/* Deuxième grille */
		vcg::GridStaticPtr<CVertexO,float> grid2;
	
		/* Il a aussi un tableau de vertex pour y stocker les vertex les plus bas de chaque case de la grille
		   Ils sont rangés dans le même ordre que les cellules de la grille
		   la cellule[0] a pour point le plus bas le point d'indice zéro de ce tableau
		 */
		std::vector<CVertexO> ptsMin;
};

#endif // Filter_Hough_Circle_H
